#![allow(dead_code)]

struct FromStrLrn {}

impl FromStrLrn {
    fn hello() {
        println!("FromStr learnning!");
    }
}

#[cfg(test)]
mod tests {
    // use super::*;

    use std::str::FromStr;

    #[test]
    /// &str 转换 struct
    fn impl_from_str() {
        #[derive(Debug, PartialEq)]
        struct Point {
            x: i32,
            y: i32,
        }

        #[derive(Debug, PartialEq)]
        struct ParsePointErr;

        impl FromStr for Point {
            type Err = ParsePointErr;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                let (x, y) = s
                    .strip_prefix('(')
                    .and_then(|s| s.strip_suffix(')'))
                    .and_then(|s| s.split_once(','))
                    .ok_or(ParsePointErr)?;

                let x_fromstr = x.parse::<i32>().map_err(|_| ParsePointErr)?;
                let y_fromstr = y.parse::<i32>().map_err(|_| ParsePointErr)?;

                Ok(Point {
                    x: x_fromstr,
                    y: y_fromstr,
                })
            }
        }

        let expected = Ok(Point { x: 1, y: 2 });

        // 显示调用
        assert_eq!(Point::from_str("(1,2)"), expected);
        // 隐式调用
        assert_eq!("(1,2)".parse(), expected);
        assert_eq!("(1,2)".parse::<Point>(), expected);
        // 输入字符串无效
        assert!(Point::from_str("(1 2)").is_err());
    }

    #[test]
    fn already_impl_from_str() {
        let str = String::from("false");
        let var = str.as_str().parse::<bool>().unwrap();
        assert!(!var);

        let str = String::from("456");
        let num = str.parse::<i32>().unwrap();
        assert_eq!(num, 456);

        let str = "45.67";
        let float = str.parse::<f32>().unwrap();
        assert_eq!(float, 45.67);
    }
}
